﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace WJP.Localization
{
    /// <summary>
    /// 语言提供器
    /// </summary>
    public abstract class Translator
    {
        /// <summary>
        /// 是否直接使用开发语言
        /// </summary>
        public bool IsDevCulture { get; set; }

        /// <summary>
        /// 是否启用整个多语言功能
        /// </summary>
        public virtual bool Enable { get; set; }

        /// <summary>
        /// 是否启动语言收集功能
        /// </summary>
        public bool AutoCollect
        {
            get { return Enable && AutoCollect; }
            set { }
        }

        public string CurrentCulture
        {
            get { return CurrentCulture; }
            set
            {
                if (CurrentCulture == value)
                    return;
                CurrentCulture = value;
                IsDevCulture = GetIsDevCulture(CurrentCulture);
                OnCurrentCultureChanged();
            }
        }

        /// <summary>
        /// 获取收集到的所有字符串
        /// </summary>
        protected IList<string> CollectedList { get; } = new List<string>(100);

        /// <summary>
        /// 忽略采集的字符串
        /// </summary>
        private List<string> IgnoredCollect { get; set; } = new List<string>();

        /// <summary>
        /// 当前文化项发生改变时的事件。
        /// </summary>
        protected virtual void OnCurrentCultureChanged()
        {
        }

        /// <summary>
        /// 判断指定的语言是否为开发语言。
        /// </summary>
        /// <param name="language"></param>
        /// <returns></returns>
        public static bool GetIsDevCulture(string language)
        {
            return string.IsNullOrEmpty(language) || language.EqualsIgnoreCase(PlatformEnvironment.Configuration.DevCulture);
        }

        /// <summary>
        /// 收集某个开发语言
        /// </summary>
        /// <param name="devCulture"></param>
        protected void Collect(string devCulture)
        {
            if (!AutoCollect)
                return;
            if (IgnoredCollect.Contains(devCulture))
                return;

            if (!CollectedList.Contains(devCulture))
            {
                CollectedList.Add(devCulture);
                OnCollected(devCulture);
            }
        }

        /// <summary>
        /// 某个开发语言被收集后发生。
        /// </summary>
        /// <param name="devCulture"></param>
        protected virtual void OnCollected(string devCulture)
        {
        }

        /// <summary>
        /// 忽略某个字符串的收集。
        ///
        /// 一般使用在动态拼接字符串的情况下。
        /// </summary>
        /// <param name="words">一个不希望被翻译引擎收集的字符串。</param>
        internal void IgnoreCollect(string words)
        {
            if (!this.AutoCollect)
                return;
            this.IgnoredCollect.Add(words);
        }

        /// <summary>
        /// 通过代码中直接编写的语言，翻译为对应当前语言。
        /// <para>实现时，注意，此方法与 TranslateReverse 互为可逆的操作。</para>
        /// </summary>
        /// <param name="devCulture">代码中直接编写的语言</param>
        /// <returns></returns>
        public string Translate(string devCulture)
        {
            if (!IsDevCulture && Enable && devCulture.IsNotEmpty())
            {
                devCulture = devCulture.Trim();
                if (devCulture.Contains(System.Environment.NewLine))
                {
                    var strArray = devCulture.Split(System.Environment.NewLine.ToCharArray(),
                        StringSplitOptions.RemoveEmptyEntries);
                    string translate = string.Empty;
                    foreach (var str in strArray)
                    {
                        if (!TranslateCore(str, out string result))
                        {
                            result = str;
                            Collect(str);
                        }

                        translate += result + System.Environment.NewLine;
                    }

                    return translate;
                }

                if (TranslateCore(devCulture, out string result2))
                    return result2;
                Collect(devCulture);
            }

            return devCulture;
        }

        /// <summary>
        /// 通过代码中直接编写的语言，翻译为对应当前语言。
        ///
        /// 实现时，注意，此方法与 TranslateReverseCore 互为可逆的操作。
        /// </summary>
        /// <param name="devCulture">代码中直接编写的语言。</param>
        /// <param name="result">翻译后的结果。</param>
        /// <returns>是否成功翻译。如果翻译失败，基类会把结果收集起来。</returns>
        protected abstract bool TranslateCore(string devCulture, out string result);

        /// <summary>
        /// 通过当前语言，翻译为对应代码中直接编写的语言。
        ///
        /// 实现时，注意，此方法与 Translate 互为可逆的操作。
        /// </summary>
        /// <param name="currentCulture">当前语言对应的语句。</param>
        /// <returns></returns>
        public string TranslateReverse(string currentCulture)
        {
            if (IsDevCulture || !Enable)
                return currentCulture;
            return this.TranslateReverse(currentCulture);
        }

        /// <summary>
        /// 通过当前语言，翻译为代码中直接编写的语言。
        ///
        /// 实现时，注意，此方法与 TranslateCore 互为可逆的操作。
        /// </summary>
        /// <param name="currentCulture"></param>
        /// <returns></returns>
        protected abstract string TranslateReverseCore(string currentCulture);

        /// <summary>
        /// 所有支持的语言。
        /// </summary>
        /// <returns></returns>
        public abstract IList<string> GetSupportCultures();
    }
}